import arrMethods from './arr'

export function observe(data) { 


	//  data 不是对象 或者为空
	if (typeof data !== 'object' || data == null) {
		return data
	}

	// 1 是对象时  
	return new Observer(data)
}

//vue2 通过 Object.defineProperty 实现数据劫持 缺点 只能同时监听对象中得一个属性
class Observer {
  // 构造函数，接收一个值作为参数
	constructor(value) {

    // 使用Object.defineProperty给传入的值添加一个不可枚举的属性__ob__，指向当前Observer实例
		Object.defineProperty(value,'__ob__',{
			enumerable:false, // 不可枚举属性
			value:this,
		})

		if (Array.isArray(value)) {  // 数组的处理
			value.__proto__ = arrMethods
			this.observeArray(value)
		} else {    // 对象处理
			this.walk(value)
		}
	}
	walk(data) {
		let keys = Object.keys(data)
		for (let i = 0; i < keys.length; i++) {
			let key = keys[i]
			let value = data[key]
			defineReactive(data, key, value)
		}
	}
	observeArray(value) {
		for (let i = 0; i < value.length; i++) {
			observe(value[i])
		}
	}
}
//  给对象中的属性进行劫持
function defineReactive(data, key, value) {
	// 递归劫持对象中的属性值
	if (typeof value === 'object') {
		observe(value)
	}

	Object.defineProperty(data, key, {
		get() {
			return value
		},
		set(newVal) {
			if (newVal === value) return;
			// 设置新值
			observe(newVal)
			value = newVal
			// observe(value)

		}
	})
}

